#include "../../include/CLink/App/Application.h"
#include "../../include/CLink/Router/Router.h"
#include "../../include/CLink/database/DatabaseManager.h"

#include <Poco/Util/HelpFormatter.h>
#include <Poco/Util/Option.h>
#include <Poco/Util/OptionSet.h>
#include <Poco/Util/OptionProcessor.h>
#include <Poco/File.h>
#include <Poco/Path.h>
#include <Poco/Logger.h>
#include <Poco/FileChannel.h>
#include <Poco/PatternFormatter.h>
#include <Poco/FormattingChannel.h>
#include <Poco/AsyncChannel.h>
#include <Poco/AutoPtr.h>
#include <Poco/Exception.h>
#include <iostream>

using Poco::AsyncChannel;
using Poco::AutoPtr;
using Poco::File;
using Poco::FileChannel;
using Poco::FormattingChannel;
using Poco::Logger;
using Poco::Path;
using Poco::PatternFormatter;
using Poco::Util::HelpFormatter;
using Poco::Util::Option;
using Poco::Util::OptionCallback;
using Poco::Util::OptionSet;

namespace CLink
{
namespace App
{

void Application::initialize(Poco::Util::Application &self)
{
	_helpRequested = false;
    _versionRequested = false;
    // 调用基类的initialize方法
    ServerApplication::initialize(self);

    // 设置应用名称和版本
    _appName = config().getString("application.name", "CLink");
    _version = config().getString("application.version", "1.0.0");

    // 设置根目录
    _rootDir = config().getString("application.rootDir", Poco::Path::current());
    loadConfiguration(getConfigDir() + "/config.ini");
    // 创建必要的目录结构
    createDirectories();

    // 初始化日志
    initializeLogging();

    // 初始化配置
    initializeConfig();

    // 初始化数据库
    initializeDatabase();

    // 初始化HTTP服务器
    initializeHttpServer();

    // 注册路由
    registerRoutes();

    logger().information("Application initialized: " + _appName + " v" + _version);
}

void Application::uninitialize()
{
    // 关闭HTTP服务器
    logger().information("Shutting down HTTP server...");
    _httpServer->stop();

    // 关闭数据库连接
    try
    {
        logger().information("Closing database connections...");
        _databaseManager->shutdown();
    }
    catch (const std::exception &ex)
    {
        logger().error("Error closing database connections: " + std::string(ex.what()));
    }

    logger().information("Application shutdown complete");

    // 调用基类的uninitialize方法
    ServerApplication::uninitialize();
}

void Application::defineOptions(OptionSet &options)
{
    // 调用基类的defineOptions方法
    ServerApplication::defineOptions(options);

    // 定义应用程序特定的选项
    options.addOption(
        Option("help", "h", "Display help information")
            .required(false)
            .repeatable(false)
            .callback(OptionCallback<Application>(this, &Application::handleOption)));

    options.addOption(
        Option("version", "v", "Display version information")
            .required(false)
            .repeatable(false)
            .callback(OptionCallback<Application>(this, &Application::handleOption)));

    options.addOption(
        Option("config", "c", "Load configuration from the given file")
            .required(false)
            .repeatable(false)
            .argument("file")
            .callback(OptionCallback<Application>(this, &Application::handleOption)));
}

void Application::handleOption(const std::string &name, const std::string &value)
{
    if (name == "help")
    {
        _helpRequested = true;
        stopOptionsProcessing();
    }
    else if (name == "version")
    {
        _versionRequested = true;
        stopOptionsProcessing();
    }
    else if (name == "config")
    {
        _configFile = value;
        loadConfiguration(value);
    }
}

int Application::main(const std::vector<std::string> &args)
{
    // 如果请求了帮助信息，显示帮助并退出
    if (_helpRequested)
    {
        displayHelp();
        return Application::EXIT_OK;
    }

    // 如果请求了版本信息，显示版本并退出
    if (_versionRequested)
    {
        displayVersion();
        return Application::EXIT_OK;
    }

    // 启动HTTP服务器
    logger().information("Starting HTTP server...");
    _httpServer->start();
    logger().information("HTTP server started");

    // 等待服务器终止
    waitForTerminationRequest();

    // 返回成功退出代码
    return Application::EXIT_OK;
}

void Application::initializeLogging()
{
    try
    {
        // 创建日志目录
        std::string logDir = getLogDir();
        File logDirFile(logDir);
        if (!logDirFile.exists())
        {
            logDirFile.createDirectories();
        }

        // 创建文件通道
        std::string logFilePath = Path(logDir, _appName + ".log").toString();
        AutoPtr<FileChannel> fileChannel(new FileChannel(logFilePath));
        fileChannel->setProperty("rotation", "10 M");
        fileChannel->setProperty("archive", "timestamp");
        fileChannel->setProperty("purgeAge", "12 months");

        // 创建格式化器
        AutoPtr<PatternFormatter> formatter(new PatternFormatter);
        formatter->setProperty("pattern", "%Y-%m-%d %H:%M:%S.%i [%p] [%s] %t");

        // 创建格式化通道
        AutoPtr<FormattingChannel> formattingChannel(new FormattingChannel(formatter, fileChannel));

        // 创建异步通道
        AutoPtr<AsyncChannel> asyncChannel(new AsyncChannel(formattingChannel));

        // 配置根日志记录器
        Logger::root().create("file", asyncChannel);
        Logger::root().setLevel(config().getString("logger.level", "information"));

        logger().information("Async logging initialized");
    }
    catch (const Poco::Exception &ex)
    {
        std::cerr << "Error initializing logging: " << ex.displayText() << std::endl;
    }
    catch (const std::exception &ex)
    {
        std::cerr << "Error initializing logging: " << ex.what() << std::endl;
    }
}

void Application::initializeConfig()
{
    try
    {
        // 可以在这里添加特定配置项的验证
        if (!config().hasProperty("http.port"))
        {
            logger().warning("No HTTP port configured, using default 8080");
        }
    }
    catch (const Poco::Exception &ex)
    {
        logger().error("Error initializing configuration: " + ex.displayText());
        throw; // 重新抛出异常，让应用程序终止
    }
}

void Application::initializeDatabase()
{
    try
    {
        // 获取数据库配置
        std::string dbType = config().getString("database.type", "sqlite");
        std::string dbHost = config().getString("database.host", "localhost");
        std::string dbPort = config().getString("database.port", "3306");
        std::string dbName = config().getString("database.name", _appName);
        std::string dbUser = config().getString("database.user", "root");
        std::string dbPassword = config().getString("database.password", "");
        int dbPoolSize = config().getInt("database.poolSize", 10);
		std::string dbFile = config().getString("database.file", "./data/sqlite.db");

        CLink::Db::ConnectionConfig conf;
#ifdef _WIN32
        conf.type = (dbType == "sqlite") ? CLink::Db::DatabaseType::SQLITE : CLink::Db::DatabaseType::MYSQL;
#else
        // 非Windows平台只支持SQLite
        conf.type = CLink::Db::DatabaseType::SQLITE;
#endif
        conf.host = dbHost;
        conf.port = Poco::NumberParser::parse(dbPort);
        conf.database = dbName;
        conf.username = dbUser;
        conf.password = dbPassword;
        conf.charset = "utf8";
        bool inMemory = config().getBool("database.in_memory", false);
        conf.inMemory = inMemory && (conf.type == CLink::Db::DatabaseType::SQLITE);
        conf.minSessions = 1;
        conf.maxSessions = dbPoolSize;
        conf.idleTime = 60;
		conf.database = inMemory ? ":memory:" : dbFile; // 如果是SQLite且in_memory为true，则使用内存数据库
        
        _databaseManager.reset(new CLink::Db::DatabaseManager);
        // 初始化数据库连接
        _databaseManager->initialize(conf);

        logger().information("Database initialized: " + dbType + "://" + dbUser + "@" + dbHost + ":" + dbPort + "/" + dbName);
    }
    catch (const Poco::Exception &ex)
    {
        logger().error("Error initializing database: " + ex.displayText());
    }
    catch (const std::exception &ex)
    {
        logger().error("Error initializing database: " + std::string(ex.what()));
    }
}

void Application::initializeHttpServer()
{
    try
    {
        // 获取HTTP服务器配置
        CLink::Server::ServerConfig conf;
        conf.port = config().getInt("http.port", 8080);
        conf.maxThreads = config().getInt("http.maxThreads", 16);
        conf.maxQueued = config().getInt("http.maxQueued", 100);
        conf.timeout = config().getInt("http.timeout", 60);
        conf.keepAlive = config().getBool("http.keepAlive", false);

        // 获取HTTPS配置，如果启用HTTPS，会包含http的配置
        conf.enableHttps = config().getBool("https.enableHttps", false);
        if (conf.enableHttps)
        {
            conf.securePort = config().getInt("https.securePort", 443);
            conf.keyFile = config().getString("https.keyFile");
            conf.certFile = config().getString("https.certFile");
            conf.caLocation = config().getString("https.caLocation", "");
        }
        // 创建HTTP服务器
        _httpServer = std::make_shared<CLink::Server::Server>();
        _httpServer->setLogger(logger());
        _httpServer->initialize(conf);
    }
    catch (const Poco::Exception &ex)
    {
        logger().error("Error initializing HTTP server: " + ex.displayText());
    }
    catch (const std::exception &ex)
    {
        logger().error("Error initializing HTTP server: " + std::string(ex.what()));
    }
}

void Application::registerRoutes()
{
    try
    {
        getRouter()->setDBManager(_databaseManager);
		// 调用注册回调函数
        for (const auto &callback : _registerCallbacks)
        {
            callback(getRouter());
		}
        logger().information("Routes registered");
    }
    catch (const std::exception &ex)
    {
        logger().error("Error registering routes: " + std::string(ex.what()));
        exit(-1);
    }
}

void Application::createDirectories()
{
    try
    {
        // 创建必要的目录结构
        std::vector<std::string> dirs = {
            getConfigDir(),
            getLogDir(),
            getDataDir(),
            getTempDir(),
            getStaticDir(),
            getUploadDir()};

        for (const auto &dir : dirs)
        {
            File dirFile(dir);
            if (!dirFile.exists())
            {
                dirFile.createDirectories();
            }
        }
    }
    catch (const Poco::Exception &ex)
    {
        std::cerr << "Error creating directories: " << ex.displayText() << std::endl;
    }
    catch (const std::exception &ex)
    {
        std::cerr << "Error creating directories: " << ex.what() << std::endl;
    }
}

void Application::displayHelp()
{
    HelpFormatter helpFormatter(options());
    helpFormatter.setCommand(commandName());
    helpFormatter.setUsage("OPTIONS");
    helpFormatter.setHeader(_appName + " v" + _version + "\n"
                                                            "A C++ web application framework based on Poco.");
    helpFormatter.format(std::cout);
}

CLink::Router::Router* Application::getRouter()
{
    return _httpServer->getRouter();
}

void Application::addRegister(const std::function<void(CLink::Router::Router*)>& callback)
{
	_registerCallbacks.push_back(callback);
}

void Application::displayVersion()
{
    std::cout << _appName << " v" << _version << std::endl;
}

std::string Application::getConfigDir() const
{
    return Path(_rootDir, "config").toString();
}

std::string Application::getLogDir() const
{
    return Path(_rootDir, "logs").toString();
}

std::string Application::getDataDir() const
{
    return Path(_rootDir, "data").toString();
}

std::string Application::getTempDir() const
{
    return Path(_rootDir, "temp").toString();
}

std::string Application::getStaticDir() const
{
    return Path(_rootDir, "static").toString();
}

std::string Application::getUploadDir() const
{
    return Path(_rootDir, "uploads").toString();
}
}
}